#

| Chapter 44 Shell Programming for the Uninitiated |

## 44.15 Handling Command-Line Arguments in Shell Scripts

To write flexible shell scripts, you usually want to give them command-line arguments. As you've seen in other articles (44.11, 44.12), `$1` holds the first command-line argument. The Bourne shell can give you arguments through the ninth, `$9`. The Korn Shell and some other newer Bourne-type shells understand `${10}` for the tenth argument, and so on. (Article 8.5 has an overview of the shell's command-line handling.)

### 44.15.1 With the $@"

If you've been reading this series (44.1) of articles in order, you saw the zpg (44.12) script that accepted just one command-line argument. If you put `"$@"` in a script, the shell will replace that string with a quoted (8.14) set of the script's command-line arguments. Then you can pass as many arguments as you want, including pathnames with unusual characters (23.11):

>     % zpg report memo "savearts/What's next?"

The third argument has a perfectly legal filename; we see more and more of them on our system - especially filesystems that are networked to computers like the Macintosh, where spaces and other "special" characters in filenames are common. Double-quoting all arguments through the script helps to be sure that the script can handle these unusual (but legal!) pathnames.

In this case, we want the arguments to be passed to the gzcat command. Let's change the zpg script to read:

>     gzcat "$@" >$temp

When the shell runs the script with the arguments shown above, the command line will become:

>     gzcat "report" "memo" "savearts/What's next?" >/tmp/zpg12345

> NOTE: On some Bourne shells, if there are no command-line arguments, the `"$@"` becomes a single empty argument (46.7), as if you'd typed this:

> >     gzcat "" >/tmp/zpg12345

> In this case, the gzcat command would complain that it can't find a file. (Of course, in this script, the case would prevent this problem. But not all scripts test the number of arguments.)

> On those shells, you can replace `"$@"` with `${1+"$@"}` (45.12). That means that if `$1` is defined, `"$@"` should be used. A less-good fix is to replace `"$@"` with `$*`. It gives you an unquoted list of command-line arguments; that's usually fine but can cause trouble on pathnames with special characters in them.

### 44.15.2 With a Loop

A for loop (44.16) can step through all command-line arguments, one by one. You can also use a while loop (44.10) that tests `$#` (see later in this chapter) and removes the arguments one by one with the shift command (44.17). The getopt and getopts (44.18) commands handle arguments in a more standard way.

### 44.15.3 Counting Arguments with $#

The `$#` parameter counts the number of command-line arguments. For instance, if there are three arguments, `$#` will contain `3`. This is usually used for error-checking (as in the zpg script in article 44.12) with case (44.5) or test (44.20).

- JP

44.14 Putting awk, sed, etc., Inside Shell Scripts |  | 44.16 Handling Command-Line Arguments with a for Loop